package com.ticket.daoImpl;

import com.ticket.dao.IDbDAO;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 *  数据层接口实现类
 * @Description:提供常用对增删改查功能
 */
@SuppressWarnings("unchecked")
@Transactional(rollbackFor=Exception.class)
public class DbDAOImpl implements IDbDAO {

	@PersistenceContext
	private EntityManager entityManager = null;
	
	public void merge(Object object) {
		entityManager.merge(object);
	}
	
	public void persist(Object object) {
		entityManager.persist(object);
	}

	public void remove(Object object) {
		
			String id = null;
			try {
				Method getId = object.getClass().getMethod("getId");
				id = (String)getId.invoke(object);
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			Object obj = entityManager.find(object.getClass(), id);
			entityManager.remove(obj);
	}
	
	public <T> T get(Class<T> c, String id) {
		
		T t = entityManager.find(c, id);
		return t;
	}
	
	public List<Object[]> executeSQLForQuery(String sqlString, Object...values){
		
		Query query = entityManager.createNativeQuery(sqlString).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		List<Object[]> list = query.getResultList();
		
		return list;
	}
	
	public <T> List<T> executeSQLForQuery(String sqlString, Class<T> c,
			Object... values) {
	
		Query query = entityManager.createNativeQuery(sqlString, c).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		List<T> list = query.getResultList();
		
		return list;
	}
	
	public <T> List<T> executeSQLForQuery(String jpqlString, Class<T> c,
			Integer start, Integer count, Object... values) {
		Query query = entityManager.createNativeQuery(jpqlString, c).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		if(start != null){
			query.setFirstResult(start);
		}
		if(count != null){
			query.setMaxResults(count);
		}

		List<T> list = query.getResultList();
		return list;
	}

	public <T> T executeSQLForQuerySingle(String sqlString, Class<T> c,Object... values) {
		
		List<T> list = executeSQLForQuery(sqlString, c, 0, 1, values);
		if(list.size() != 0){
			
			return list.get(0);
		}
		return null;
	}

	public int executeSQLForUpdate(String sqlString, Object... values) {
		
		Query query = entityManager.createNativeQuery(sqlString).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		int list = query.executeUpdate();
		return list;
	}
	
	public String executeSQLForQuerySingle(String sqlString, Object...values){

		List<Object[]> list = this.executeSQLForQuery(sqlString, values);
		if(list == null || list.isEmpty()){
			
			return null;
		}
		return list.get(0)[0].toString();
	}
	
	public List<Object> executeJPQLForQuery(String jpqlString, Object... values) {
		
		return executeJPQLForQuery(jpqlString, null, null, values);
	}

	public Object executeJPQLForQuerySingle(String jpqlString, Object... values) {
		
		List<Object> list = this.executeJPQLForQuery(jpqlString, Object.class, 0, 1, values);
		if(list == null || list.isEmpty()){
			
			return null;
		}
		return list.get(0);
	}

	public int executeJPQLForUpdate(String sqlString, Object...values) {
		
		Query query = entityManager.createQuery(sqlString).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		int list = query.executeUpdate();
		return list;
	}

	public <T> List<T> executeJPQLForQuery(String jpqlString, Class<T> c,
			Object... values) {
		
		return executeJPQLForQuery(jpqlString, c, null, null, values);
	}

	public <T> T executeJPQLForQuerySingle(String jpqlString, Class<T> c,
			Object... values) {
		
		List<T> list = executeJPQLForQuery(jpqlString, c, 0, 1, values);
		if(list.size() != 0){
			
			return list.get(0);
		}
		return null;
	}

	public List<Object> executeJPQLForQuery(String jpqlString, Integer start,
			Integer count, Object... values) {
		
		return executeJPQLForQuery(jpqlString, Object.class, start, count, values);
	}

	public <T> List<T> executeJPQLForQuery(String jpqlString, Class<T> c,
			Integer start, Integer count, Object... values) {
		
		Query query = entityManager.<T>createQuery(jpqlString, c).setHint("org.hibernate.cacheable", true);
		for(int i = 0; i < values.length; i++){
			
			query.setParameter(i+1, values[i]);
		}
		if(start != null){
			query.setFirstResult(start);
		}
		if(count != null){
			query.setMaxResults(count);
		}
		
		List<T> list = query.getResultList();
		return list;
	}
}